<?php

/**
 * 获取GUID
 * @param string $sp 分隔符
 * @return string
 */
function getGuid($sp = "")
{
    @list($usec, $sec) = explode(" ", microtime());
    $currentTimeMillis = $sec . substr($usec, 2, 3);

    $tmp = rand(0, 1) ? '-' : '';
    $nextLong = $tmp . rand(1000, 9999) . rand(1000, 9999) . rand(1000, 9999) . rand(100, 999) . rand(100, 999);
    $getHostID = SiteHash;
    $valueBeforeMD5 = $getHostID . ':' . $currentTimeMillis . ':' . $nextLong;
    $valueAfterMD5 = md5($valueBeforeMD5);
    $raw = strtoupper($valueAfterMD5);

    return substr($raw, 0, 8) . $sp . substr($raw, 8, 4) . $sp . substr($raw, 12, 4) . $sp . substr($raw, 16, 4) . $sp . substr($raw, 20);
}


/**
 * 获取CUID（短一些的GUID）
 * @return string
 */
function getCuid()
{
    @list($usec, $sec) = explode(" ", microtime());
    //$sec = substr($sec, 0, 6);
    $sec_a = substr($sec, 2, 3) + rand(100, 999);
    $sec_b = substr($sec, 5, 5) + rand(100, 999);
    $str_sec = base62_int2str($sec_a) . base62_int2str($sec_b);
    $str_usec = base62_int2str(($usec + rand(1, 9)) * 1000000);
    $left = $str_sec . $str_usec . base62_int2str(rand(1000, 9999));

    if (strlen($left) < 12) {
        $left .= base62_int2str(rand(0, 9));
    }

    return strtoupper($left);
}


/**
 * 生产一个唯一的订单号
 * @param string $prefix
 * @return string $order_no
 */
function build_order_no($prefix = '')
{
    return $prefix . date('YmdHi') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}


/**
 * XML编码
 * @param mixed $data 数据
 * @param string $encoding 数据编码
 * @param string $root 根节点名
 * @return string
 */
function xml_encode($data, $encoding = 'utf-8', $root = 'root')
{
    $xml = '<?xml version="1.0" encoding="' . $encoding . '"?>';
    $xml .= '<' . $root . '>';
    $xml .= data_to_xml($data);
    $xml .= '</' . $root . '>';
    return $xml;
}

/**
 * 数据XML编码
 * @param mixed $data 数据
 * @return string
 */
function data_to_xml($data)
{
    $xml = '';
    foreach ($data as $key => $val) {
        is_numeric($key) && $key = "item id=\"$key\"";
        $xml .= "<$key>";
        $xml .= (is_array($val) || is_object($val)) ? data_to_xml($val) : $val;
        list($key,) = explode(' ', $key);
        $xml .= "</$key>";
    }
    return $xml;
}

/*
 * 如果使用了此键进行加密，如果更换了sitehash，将导致无法解密
 * 加密解密
 */
function safe_key()
{
    return md5(SiteHash);
}

/**
 * xxtea加密
 * @param $txt 明文
 * @param $key 密码
 * @return array|string|string[]
 */
function safe_xxtea_encrypt($txt, $key = '')
{
    empty($key) AND $key = safe_key();
    $encrypt = xxtea_encrypt($txt, $key);
    return safe_urlencode(base64_encode($encrypt));
}

/**
 * xxtea解密
 * @param $txt 密文
 * @param $key 密码
 * @return false|string
 */
function safe_xxtea_decrypt($txt, $key = '')
{
    empty($key) AND $key = safe_key();
    $encrypt = base64_decode(safe_urldecode($txt));
    $ret = xxtea_decrypt($encrypt, $key);
    return $ret;
}


//xxtea_encrypt的php实现
if (!function_exists('xxtea_encrypt')) {
    function xxtea_long2str($v, $w)
    {
        $len = count($v);
        $n = ($len - 1) << 2;
        if ($w) {
            $m = $v[$len - 1];
            if (($m < $n - 3) || ($m > $n)) return FALSE;
            $n = $m;
        }
        $s = array();
        for ($i = 0; $i < $len; $i++) {
            $s[$i] = pack("V", $v[$i]);
        }
        if ($w) {
            return substr(join('', $s), 0, $n);
        } else {
            return join('', $s);
        }
    }

    function xxtea_str2long($s, $w)
    {
        $v = unpack("V*", $s . str_repeat("\0", (4 - strlen($s) % 4) & 3));
        $v = array_values($v);
        if ($w) {
            $v[count($v)] = strlen($s);
        }
        return $v;
    }

    function xxtea_int32($n)
    {
        while ($n >= 2147483648) $n -= 4294967296;
        while ($n <= -2147483649) $n += 4294967296;
        return (int)$n;
    }

    function xxtea_encrypt($str, $key)
    {
        if ($str == '') return '';
        $v = xxtea_str2long($str, TRUE);
        $k = xxtea_str2long($key, FALSE);
        if (count($k) < 4) {
            for ($i = count($k); $i < 4; $i++) {
                $k[$i] = 0;
            }
        }
        $n = count($v) - 1;
        $z = $v[$n];
        $y = $v[0];
        $delta = 0x9E3779B9;
        $q = floor(6 + 52 / ($n + 1));
        $sum = 0;
        while (0 < $q--) {
            $sum = xxtea_int32($sum + $delta);
            $e = $sum >> 2 & 3;
            for ($p = 0; $p < $n; $p++) {
                $y = $v[$p + 1];
                $mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
                $z = $v[$p] = xxtea_int32($v[$p] + $mx);
            }
            $y = $v[0];
            $mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
            $z = $v[$n] = xxtea_int32($v[$n] + $mx);
        }
        return xxtea_long2str($v, FALSE);
    }

    function xxtea_decrypt($str, $key)
    {
        if ($str == '') return '';
        $v = xxtea_str2long($str, FALSE);
        $k = xxtea_str2long($key, FALSE);
        if (count($k) < 4) {
            for ($i = count($k); $i < 4; $i++) {
                $k[$i] = 0;
            }
        }
        $n = count($v) - 1;
        $z = $v[$n];
        $y = $v[0];
        $delta = 0x9E3779B9;
        $q = floor(6 + 52 / ($n + 1));
        $sum = xxtea_int32($q * $delta);
        while ($sum != 0) {
            $e = $sum >> 2 & 3;
            for ($p = $n; $p > 0; $p--) {
                $z = $v[$p - 1];
                $mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
                $y = $v[$p] = xxtea_int32($v[$p] - $mx);
            }
            $z = $v[$n];
            $mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
            $y = $v[0] = xxtea_int32($v[0] - $mx);
            $sum = xxtea_int32($sum - $delta);
        }
        return xxtea_long2str($v, TRUE);
    }
}

/**
 * 对密码进行加密
 * @param string $password 密码
 * @param string $solt 盐
 * @return string
 */
function safe_password_md5($password, $solt = '')
{
    $password_md5 = md5($password . $solt);
    return md5(substr($password_md5, 0, 10) . $password_md5);
}

/**
 * 自动处理GET POST COOKIE中值的转义
 * @return bool
 */
function _stripslashes()
{
    if (version_compare(PHP_VERSION, '5.4', '>=')) {
        return false;
    }
    if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
        if (isset($_GET)) {
            $_GET = _stripslashes_deep($_GET);
        }
        if (isset($_POST)) {
            $_POST = _stripslashes_deep($_POST);
        }
        if (isset($_COOKIE)) {
            $_COOKIE = _stripslashes_deep($_COOKIE);
        }
    }
}

/**
 * 递归转义处理
 * @param $value
 * @return array|string
 */
function _stripslashes_deep($value)
{
    if (empty($value)) {
        return $value;
    } else {
        return is_array($value) ? array_map('_stripslashes_deep', $value) : stripslashes($value);
    }
}

/**
 * URL编码安全编码
 * @param $s
 * @return array|string|string[]
 */
function safe_urlencode($s)
{
    $s = urlencode($s);
    $s = str_replace('_', '_5f', $s);
    $s = str_replace('-', '_2d', $s);
    $s = str_replace('.', '_2e', $s);
    $s = str_replace('+', '_2b', $s);
    $s = str_replace('=', '_3d', $s);
    $s = str_replace('%', '_', $s);
    return $s;
}

/**
 * URL编码安全解码
 * @param $s
 * @return string
 */
function safe_urldecode($s)
{
    $s = str_replace('_', '%', $s);
    $s = urldecode($s);
    return $s;
}

/**
 * json解码
 * @param $json
 * @return mixed
 */
function safe_json_decode($json)
{
    $json = trim($json, "\xEF\xBB\xBF");
    $json = trim($json, "\xFE\xFF");
    return json_decode($json, 1);
}

/**
 * url解码
 * @param $uri
 * @return mixed
 */
function safe_uri_decode($uri)
{
    $uri = str_replace('%28', '(', $uri);
    $uri = str_replace('%29', ')', $uri);
    $uri = str_replace('%7B', '{', $uri);
    $uri = str_replace('%7D', '}', $uri);
    $uri = str_replace('%5B', '[', $uri);
    $uri = str_replace('%5D', ']', $uri);
    $uri = str_replace('%2F', '/', $uri);
    $uri = str_replace('%3F', '?', $uri);
    $uri = str_replace('%3D', '=', $uri);
    $uri = str_replace('%26', '&', $uri);
    $uri = str_replace('+', '%20', $uri);
    $uri = str_replace('%25', '%', $uri);
    return $uri;
}

/**
 * 对转义符进行转义
 * @param $str
 * @param int $encode
 * @return mixed
 */
function escape_temp_char($str, $encode = 0)
{
    $array = array();
    $array[1] = array('\\\'', '\=', '\,', '\|', '\(', '\)', '\\`', '\array');
    $array[2] = array('--quotes--', '--equal--', '--comma--', '--vertical--', '--lbrackets--', '--rbrackets--', '--topcomma--', '--array--');
    $array[3] = array('\'', '=', ',', '|', '(', ')', '', 'array()');
    foreach ($array[1] as $key => $val) {
        if ($encode) {
            $str = str_replace($array[1][$key], $array[2][$key], $str);
        } else {
            $str = str_replace($array[2][$key], $array[3][$key], $str);
        }
    }
    return $str;
}

/**
 * base62编码
 * @param $data
 * @return string
 */
function base62_encode($data)
{
    $base62str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $data = strval($data);
    $base62 = str_split($base62str);
    $len = strlen($data);
    $i = 0;
    $tmpArr = array();
    while ($i < $len) {
        $val = $data[$i];
        $tmp = str_pad(decbin(ord($data[$i])), 8, '0', STR_PAD_LEFT);
        $temp = str_split($tmp, 4);
        $tmpArr = array_merge($tmpArr, $temp);
        ++$i;
    }
    $result = '';
    $i = 0;
    foreach ($tmpArr as $arr) {
        $temp = bindec($arr) * 4 + $i % 2;
        $result .= $base62[$temp];
        ++$i;
    }
    return $result;
}

/**
 * base62解码
 * @param $data
 * @return false|string
 */
function base62_decode($data)
{
    $base62str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $data = strval($data);
    $base62 = str_split($base62str);
    $base62Arr = array_flip($base62);
    if (!preg_match('/[a-zA-Z0-9]+/', $data)) {
        return false;
    }
    $len = strlen($data);
    $i = 0;
    $tempArr = array();
    while ($i < $len) {
        $temp = decbin(($base62Arr[$data[$i]] - $i % 2) / 4);
        $tempArr[] = str_pad($temp, 4, '0', STR_PAD_LEFT);
        ++$i;
    }
    $result = '';
    $tempArr = array_chunk($tempArr, 2);
    foreach ($tempArr as $arr) {
        $result .= chr(bindec(join('', $arr)));
    }
    return $result;
}


/**
 * 将整数转为base62字符，返回值不可逆
 * @param $x
 * @return string
 */
function base62_int2str($x)
{
    $show = '';
    while ($x > 0) {
        $s = $x % 62;
        if ($s > 35) {
            $s = chr($s + 61);
        } elseif ($s > 9 && $s <= 35) {
            $s = chr($s + 55);
        }
        $show = $s . $show;
        $x = floor($x / 62);

    }
    if (!$show)
        $show = "0";
    return $show;
}

/**
 * 将网址转为62位编码的短地址
 * @param  string $url 网址
 * @return string
 */
function shorturl($url)
{
    $url = crc32($url);
    $result = sprintf("%u", $url);
    return base62_int2str($result);
}

/**
 * URL base64解码
 * '-' -> '+'
 * '_' -> '/'
 * 字符串长度%4的余数，补'='
 * @param string $string
 * @return bool|string
 */
function urlsafe_b64decode($string)
{
    $data = str_replace(array('-', '_'), array('+', '/'), $string);
    $mod4 = strlen($data) % 4;
    if ($mod4) {
        $data .= substr('====', $mod4);
    }
    return base64_decode($data);
}

/**
 * URL base64编码
 * '+' -> '-'
 * '/' -> '_'
 * '=' -> ''
 * @param string $string
 * @return mixed|string
 */
function urlsafe_b64encode($string)
{
    $data = base64_encode($string);
    return str_replace(array('+', '/', '='), array('-', '_', ''), $data);
}
